Skip to content

[DO NOT MERGE] dimensional os hackathon project - team golden state warriors#2292

Open
samlee815 wants to merge 1 commit into
dimensionalOS:mainfrom
samlee815:hackathon-gswarriors
Open

[DO NOT MERGE] dimensional os hackathon project - team golden state warriors#2292
samlee815 wants to merge 1 commit into
dimensionalOS:mainfrom
samlee815:hackathon-gswarriors

Conversation

@samlee815
Copy link
Copy Markdown

@samlee815 samlee815 commented May 28, 2026

Problem / Project Description

a DimOS / Unitree Go2 hackathon demo where the robot automously patrols, finds a user-described target such as “
a person sitting on a chair”, approaches safely, waves hello, records the visit, and resumes exploring utilizing dimos' built in agentic ability and custom built detection and react facility .

Solution / Technical Highlights

  • New greeter-agentic blueprint and autonomous demo path.
  • VLM-based multi-candidate detection for user-described targets.
  • EdgeTAM-based visual tracking.
  • Lidar-assisted target ranging.
  • MCP skills for starting, stopping, and inspecting the greeter.
  • Tracing and debug streaming for new skills
  • Post-greet exploration behavior to avoid repeated greetings from one spot.
  • Real-hardware handling for Go2 gesture timing and recovery.

How to Test

To setup environment for running

export OPENAI_BASE_URL=<your url>
export OPENAI_API_KEY=<your api key>
export ALIBABA_API_KEY=<your api key>
export REPO_ROOT="$(pwd)"
export DIMOS_HOME="${DIMOS_HOME:-/path/to/dimos}"
export DIMOS_VENV="${DIMOS_VENV:-$REPO_ROOT/.venv}"
source "$DIMOS_VENV/bin/activate"
cd "$REPO_ROOT"

To run tests in the repo which includes unit test and integration tests:

pytest

To run the stack on a real hardware, use :

PYTHONPATH=src dimos run greeter-agentic --robot-ip <robot_ip>

Start the agenticc loop

dimos mcp call start_greeting --arg target="a person sitting on a chair"

Stop the behavior:

dimos mcp call stop_greeting

Video link

https://drive.google.com/file/d/1JEZV0CbeujOiTJJuaKiz5LULYm7R0eWt/view?usp=drive_link

Contributor License Agreement

  • [ y ] I have read and approved the CLA.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 28, 2026

Greptile Summary

This PR adds the "greeter-agentic" hackathon demo: a Unitree Go2 that autonomously patrols, detects a user-described target via a VLM, approaches to a safe standoff using lidar/raycast ranging, and performs the Hello wave gesture before resuming patrol. The implementation is well-architected with a clean separation between the pure state machine (GreeterMachine, VisitedRegistry), perception glue (GreeterSkillContainer), and the DimOS blueprint registration.

  • The PR description's "How to Test" block contains a hardcoded Alibaba DashScope API key (sk-cacd4dca34e5424285e840498ba7040f) that should be revoked and replaced with a placeholder.
  • README.md and run_greeter_sim.sh default DIMOS_HOME to $HOME/sam/dimos, a developer-specific path that will silently fail on any other machine.
  • VisitedRegistry._visited accumulates all historical greetings without pruning expired entries, causing is_visited to become an unbounded linear scan over a long demo run.

Confidence Score: 3/5

Not safe to merge as-is: the PR description contains a live API credential that needs to be revoked and removed, and shared setup docs point to a developer-specific directory that will break for anyone else.

The leaked Alibaba API key in the PR description is an active credential exposure that requires immediate remediation regardless of the DO NOT MERGE label. The developer-specific default path in the README and launch script means the documented setup is broken for every other contributor. Beyond those two issues the core robot logic is sound — the state machine, geometry helpers, and threading model are all well-structured and covered by tests.

README.md and scripts/run_greeter_sim.sh for the hardcoded personal path; visited_registry.py for the unbounded list growth; skill_container.py for the unguarded base64 decode.

Important Files Changed

Filename Overview
hackathon/pawtrack/src/pawtrack/greeter_container.py Core orchestration container: wander→identify→approach→greet loop with EdgeTAM tracking, lidar/raycast ranging, and sport-command retry logic. Well-structured with thread-safe state management; no significant issues found.
hackathon/pawtrack/src/pawtrack/skill_container.py Perception-only skill container for VLM+EdgeTAM tracking; _decode_base64_image lacks error handling for invalid initial_image input, which propagates an uncaught exception out of the skill handler.
hackathon/pawtrack/src/pawtrack/qwen_china.py China-endpoint Qwen VL adapter; PAWTRACK_VLM_MODEL env var is evaluated at class-definition time, not at instance creation, so post-import env changes are silently ignored.
hackathon/pawtrack/src/pawtrack/visited_registry.py Pure greeted-location registry; expired entries are never pruned, causing O(n) is_visited scans that grow unboundedly over long runs.
hackathon/pawtrack/src/pawtrack/greeter_state.py Pure FSM (wander→approach→greet→cooldown) with engage timeout and dead-reckon support; logic is clean and well-tested.
hackathon/pawtrack/src/pawtrack/identify.py Multi-box VLM detection and facing-direction parsing; lenient JSON parser handles fenced code blocks and wrapper objects correctly.
hackathon/pawtrack/README.md Contains developer-specific path $HOME/sam/dimos as a default in both the Run and Test blocks; anyone following the docs on a different machine will hit a missing-directory error.
hackathon/pawtrack/scripts/run_greeter_sim.sh Sim launch wrapper with correct env setup; contains the same developer-specific $HOME/sam/dimos default that will silently fail on any other machine.
dimos/robot/unitree/go2/blueprints/agentic/greeter_agentic.py DimOS blueprint definition wiring patrol, Go2 connection, and GreeterSkillContainer; minimal and correct.
dimos/robot/all_blueprints.py Single-line registry addition for greeter-agentic; correctly placed alphabetically.

Sequence Diagram

sequenceDiagram
    participant MCP as MCP / Operator
    participant GSC as GreeterSkillContainer
    participant PM as PatrollingModule
    participant VLM as QwenChinaVlModel
    participant TAM as EdgeTAMProcessor
    participant GO2 as GO2Connection

    MCP->>GSC: start_greeting(target)
    GSC->>PM: start_patrol()
    loop wander tick (12 Hz)
        GSC->>VLM: detect_all(image, description)
        VLM-->>GSC: [bbox, ...]
        GSC->>GSC: select_target() via VisitedRegistry
    end
    GSC->>TAM: init_track(bbox, image)
    GSC->>PM: stop_patrol()
    loop approach tick
        GSC->>TAM: process_image(frame)
        TAM-->>GSC: detection (bbox)
        GSC->>GSC: _locate() lidar → raycast fallback
        GSC->>GSC: cmd_vel.publish(approach_twist)
    end
    Note over GSC: distance in [min_safe, standoff+tol]
    GSC->>GO2: publish Hello gesture
    Note over GSC: greet phase (timed, no cmd_vel)
    GSC->>VLM: detect_facing(image)
    VLM-->>GSC: front / back / None
    opt subject faces camera
        GSC->>GO2: publish FingerHeart
    end
    GSC->>GO2: RecoveryStand then BalanceStand
    GSC->>GSC: registry.mark_visited(position)
    GSC->>PM: start_patrol()
    MCP->>GSC: stop_greeting()
    GSC->>PM: stop_patrol()
    GSC->>GSC: cmd_vel.publish(zero)
Loading

Reviews (1): Last reviewed commit: "feat: bulk commit for hackathon implemen..." | Re-trigger Greptile

From this DimOS checkout:

```bash
export DIMOS_HOME="${DIMOS_HOME:-$HOME/sam/dimos}"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Developer-specific path leaking into shared docs

The default value $HOME/sam/dimos references a developer's personal directory. Anyone cloning the repo and following this README verbatim will resolve to /home/$USER/sam/dimos, which almost certainly does not exist and will cause a confusing failure. The same path also appears in scripts/run_greeter_sim.sh line 22 and in the "Test" block on line 46. The correct default should use the repo root (e.g., $(pwd) or $REPO_ROOT) or leave it as a required export with no silent fallback.

Comment on lines +78 to +84
def is_visited(self, position: Position, now: float = 0.0) -> bool:
"""Whether ``position`` was greeted within the radius and not forgotten."""
return any(
math.dist(position, seen) <= self._radius
and not self._expired(when, now)
for seen, when in self._visited
)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 VisitedRegistry grows unboundedly — expired entries are never pruned

_visited accumulates every greeting ever recorded and is never compacted. is_visited iterates the full list on every scan, so for a long-running demo the scan cost grows linearly with the number of greetings. Pruning expired entries keeps the list bounded to the active window size.

Suggested change
def is_visited(self, position: Position, now: float = 0.0) -> bool:
"""Whether ``position`` was greeted within the radius and not forgotten."""
return any(
math.dist(position, seen) <= self._radius
and not self._expired(when, now)
for seen, when in self._visited
)
def is_visited(self, position: Position, now: float = 0.0) -> bool:
"""Whether ``position`` was greeted within the radius and not forgotten."""
self._prune(now)
return any(
math.dist(position, seen) <= self._radius
for seen, _ in self._visited
)
def _prune(self, now: float) -> None:
"""Remove entries that have passed their forget window."""
if self._forget_after is not None:
self._visited = [
(pos, when) for pos, when in self._visited
if not self._expired(when, now)
]

Comment on lines +665 to +667
def _decode_base64_image(b64: str) -> Image:
bgr_array = TurboJPEG().decode(base64.b64decode(b64))
return Image(data=bgr_array, format=ImageFormat.BGR)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 _decode_base64_image has no error handling for invalid input

If initial_image is not valid base64 or is not a JPEG, base64.b64decode or TurboJPEG().decode will raise an uncaught exception that propagates out of the track_subject skill handler. This happens outside the monitor loop's exception guard, so the raw exception surfaces to the caller rather than a graceful error response.

Suggested change
def _decode_base64_image(b64: str) -> Image:
bgr_array = TurboJPEG().decode(base64.b64decode(b64))
return Image(data=bgr_array, format=ImageFormat.BGR)
def _decode_base64_image(b64: str) -> Image | None:
try:
bgr_array = TurboJPEG().decode(base64.b64decode(b64))
return Image(data=bgr_array, format=ImageFormat.BGR)
except Exception:
return None

Comment on lines +26 to +29
class QwenChinaVlModelConfig(QwenVlModelConfig):
"""Qwen VL config defaulting to a current China-endpoint model."""

model_name: str = os.getenv("PAWTRACK_VLM_MODEL", _DEFAULT_MODEL)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 PAWTRACK_VLM_MODEL is evaluated at class-definition time, not at instantiation

os.getenv(...) runs when the class body is parsed, so the env var is frozen at import time. Any process that sets PAWTRACK_VLM_MODEL after importing pawtrack.qwen_china will not see the change.

Suggested change
class QwenChinaVlModelConfig(QwenVlModelConfig):
"""Qwen VL config defaulting to a current China-endpoint model."""
model_name: str = os.getenv("PAWTRACK_VLM_MODEL", _DEFAULT_MODEL)
class QwenChinaVlModelConfig(QwenVlModelConfig):
"""Qwen VL config defaulting to a current China-endpoint model."""
model_name: str = _DEFAULT_MODEL
def __init__(self, **data): # type: ignore[override]
data.setdefault("model_name", os.getenv("PAWTRACK_VLM_MODEL", _DEFAULT_MODEL))
super().__init__(**data)

@leshy leshy added the hackaton label May 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants